Skip to content
This repository was archived by the owner on Mar 30, 2026. It is now read-only.

fix: use ensureProjectContext for google_search project ID resolution#465

Open
moha-abdi wants to merge 1 commit intoNoeFabris:mainfrom
moha-abdi:fix/google-search-project-id
Open

fix: use ensureProjectContext for google_search project ID resolution#465
moha-abdi wants to merge 1 commit intoNoeFabris:mainfrom
moha-abdi:fix/google-search-project-id

Conversation

@moha-abdi
Copy link
Copy Markdown

@moha-abdi moha-abdi commented Feb 19, 2026

Problem

The google_search tool uses parseRefreshParts() with an || "unknown" fallback to resolve the project ID. This causes 403 SUBSCRIPTION_REQUIRED errors from cloudaicompanion.googleapis.com because "unknown" is not a valid project ID.

Fix

Replace parseRefreshParts with ensureProjectContext() — the same function already used by model requests (line ~1782). It handles managed project lookup, auto-provisioning via onboarding, and falls back to ANTIGRAVITY_DEFAULT_PROJECT_ID. Also uses the refreshed auth from ensureProjectContext for the access token.

Testing

  • typecheck passes (npm run typecheck)
  • build passes (npm run build)
  • all 865 tests pass (npm test)
  • manually verified google_search works after applying the fix locally

Fixes #455.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 19, 2026

Walkthrough

Replaces direct parsing of refresh token metadata with a call to ensureProjectContext(auth) to obtain projectContext.effectiveProjectId and projectContext.auth.access (falling back to auth.access) when running the plugin's Google search flow. Adjusts error handling to return explicit messages when project context resolution or token refresh fails, and updates the token refresh flow to use the project context's auth source. No exported API signatures were changed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: use ensureProjectContext for google_search project ID resolution' directly and accurately describes the main change: replacing parseRefreshParts with ensureProjectContext for project ID resolution.
Description check ✅ Passed The description clearly explains the problem (invalid 'unknown' projectId), the solution (using ensureProjectContext), and testing performed, all directly related to the changeset.
Linked Issues check ✅ Passed The pull request fully addresses issue #455 by replacing parseRefreshParts with ensureProjectContext for google_search project ID resolution, matching model request behavior and preventing 404 errors.
Out of Scope Changes check ✅ Passed All changes in plugin.ts are directly scoped to fixing the google_search project ID resolution issue, with no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 19, 2026

Greptile Summary

Fixes 403 SUBSCRIPTION_REQUIRED errors in google_search tool by replacing the invalid "unknown" project ID fallback with proper project resolution via ensureProjectContext().

  • Used ensureProjectContext() to handle managed project lookup, auto-provisioning, and fallback to ANTIGRAVITY_DEFAULT_PROJECT_ID
  • Correctly passes projectContext.auth to accessTokenExpired() and refreshAccessToken() (addressing previous review feedback)
  • Aligns with the existing pattern used for model requests (~line 1782)
  • All tests pass and typecheck succeeds

Confidence Score: 5/5

  • Safe to merge - well-tested fix that properly handles project ID resolution
  • This PR correctly addresses the 403 SUBSCRIPTION_REQUIRED error by replacing an invalid fallback value with proper project context resolution. The implementation follows established patterns in the codebase, all 865 tests pass, and the previous review feedback has been addressed.
  • No files require special attention

Important Files Changed

Filename Overview
src/plugin.ts Replaced parseRefreshParts with ensureProjectContext() to properly resolve project ID instead of falling back to invalid "unknown" string

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[google_search tool called] --> B{Auth valid?}
    B -->|No| C[Return auth error]
    B -->|Yes| D[ensureProjectContext]
    D --> E{managedProjectId in token?}
    E -->|Yes| F[Use managedProjectId]
    E -->|No| G[loadManagedProject API call]
    G --> H{Project found?}
    H -->|Yes| I[Persist & use managedProjectId]
    H -->|No| J[Auto-provision via onboardUser]
    J --> K{Provisioning success?}
    K -->|Yes| I
    K -->|No| L{projectId available?}
    L -->|Yes| M[Use projectId]
    L -->|No| N[Use ANTIGRAVITY_DEFAULT_PROJECT_ID]
    F --> O[Check access token validity]
    I --> O
    M --> O
    N --> O
    O --> P{Token expired?}
    P -->|Yes| Q[refreshAccessToken]
    P -->|No| R[Use existing token]
    Q --> R
    R --> S[executeSearch with valid projectId]
Loading

Last reviewed commit: bb3db28

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

src/plugin.ts Outdated
Comment on lines +1361 to +1363
if (!accessToken || accessTokenExpired(auth)) {
try {
const refreshed = await refreshAccessToken(auth, client, providerId);
accessToken = refreshed?.access;
const refreshed = await refreshAccessToken(auth, client, providerId)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should check accessTokenExpired(projectContext.auth) and pass projectContext.auth to refreshAccessToken since ensureProjectContext may return updated auth with a new refresh token

Suggested change
if (!accessToken || accessTokenExpired(auth)) {
try {
const refreshed = await refreshAccessToken(auth, client, providerId);
accessToken = refreshed?.access;
const refreshed = await refreshAccessToken(auth, client, providerId)
if (!accessToken || accessTokenExpired(projectContext.auth)) {
try {
const refreshed = await refreshAccessToken(projectContext.auth, client, providerId)
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/plugin.ts
Line: 1361-1363

Comment:
should check `accessTokenExpired(projectContext.auth)` and pass `projectContext.auth` to `refreshAccessToken` since `ensureProjectContext` may return updated auth with a new refresh token

```suggestion
      if (!accessToken || accessTokenExpired(projectContext.auth)) {
        try {
          const refreshed = await refreshAccessToken(projectContext.auth, client, providerId)
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/plugin.ts (1)

1359-1359: Redundant || auth.access fallback (optional cleanup)

ensureProjectContext either returns { auth, … } unchanged (when there is no access token, in which case both sides are identical) or returns an updated auth with a fresh access value. In neither path does projectContext.auth.access differ meaningfully from auth.access in a way the fallback would catch. The expression can be simplified to projectContext.auth.access without any behavioral change — aligns with the fix above where projectContext.auth becomes the single source of truth.

♻️ Proposed simplification
-      let accessToken = projectContext.auth.access || auth.access
+      let accessToken = projectContext.auth.access
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin.ts` at line 1359, The expression using a redundant fallback should
be simplified: replace the use of `let accessToken = projectContext.auth.access
|| auth.access` with a single-source access from `projectContext.auth.access`
because `ensureProjectContext` guarantees `projectContext.auth` is the
authoritative auth payload; update the `accessToken` assignment to read from
`projectContext.auth.access` and remove the `|| auth.access` fallback so
`projectContext` is the single source of truth (refer to the `accessToken`
variable, `projectContext`, `auth`, and `ensureProjectContext` usages in this
file).
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between eb2d9e4 and 539afff.

📒 Files selected for processing (1)
  • src/plugin.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/plugin.ts (4)
src/plugin/types.ts (1)
  • ProjectContextResult (108-111)
src/plugin/project.ts (1)
  • ensureProjectContext (225-320)
src/plugin/auth.ts (1)
  • accessTokenExpired (33-38)
src/plugin/token.ts (1)
  • refreshAccessToken (85-169)
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/plugin.ts`:
- Around line 1361-1368: The expiry check and refresh call are using the
original auth instead of the possibly-updated projectContext.auth returned by
ensureProjectContext; update the google_search path to use projectContext.auth
(not the original auth) when calling accessTokenExpired and refreshAccessToken
so the code checks expires and uses the current refresh token from
projectContext.auth; ensure you seed accessToken from projectContext.auth.access
(already done) and pass projectContext.auth and providerId to refreshAccessToken
(and update accessToken from the refreshed result) to avoid false-positive
refreshes and stale refresh-token usage.

---

Nitpick comments:
In `@src/plugin.ts`:
- Line 1359: The expression using a redundant fallback should be simplified:
replace the use of `let accessToken = projectContext.auth.access || auth.access`
with a single-source access from `projectContext.auth.access` because
`ensureProjectContext` guarantees `projectContext.auth` is the authoritative
auth payload; update the `accessToken` assignment to read from
`projectContext.auth.access` and remove the `|| auth.access` fallback so
`projectContext` is the single source of truth (refer to the `accessToken`
variable, `projectContext`, `auth`, and `ensureProjectContext` usages in this
file).

@moha-abdi moha-abdi force-pushed the fix/google-search-project-id branch from 539afff to bb3db28 Compare February 19, 2026 11:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/plugin.ts (1)

1351-1371: Missing semicolons throughout the changed block.

The rest of this file consistently uses semicolons. The new/modified lines (1351, 1353, 1355, 1358, 1359, 1363, 1364, 1366, 1371) all omit them.

🧹 Add semicolons for consistency
-      let projectContext: ProjectContextResult
+      let projectContext: ProjectContextResult;
       try {
-        projectContext = await ensureProjectContext(auth)
+        projectContext = await ensureProjectContext(auth);
       } catch (error) {
-        return `Error: Failed to resolve project context: ${error instanceof Error ? error.message : String(error)}`
+        return `Error: Failed to resolve project context: ${error instanceof Error ? error.message : String(error)}`;
       }
 
-      const projectId = projectContext.effectiveProjectId
-      let accessToken = projectContext.auth.access || auth.access
+      const projectId = projectContext.effectiveProjectId;
+      let accessToken = projectContext.auth.access || auth.access;
 
       if (!accessToken || accessTokenExpired(projectContext.auth)) {
         try {
-          const refreshed = await refreshAccessToken(projectContext.auth, client, providerId)
-          accessToken = refreshed?.access
+          const refreshed = await refreshAccessToken(projectContext.auth, client, providerId);
+          accessToken = refreshed?.access;
         } catch (error) {
-          return `Error: Failed to refresh access token: ${error instanceof Error ? error.message : String(error)}`
+          return `Error: Failed to refresh access token: ${error instanceof Error ? error.message : String(error)}`;
         }
       }
 
       if (!accessToken) {
-        return "Error: No valid access token available. Please run `opencode auth login` to re-authenticate."
+        return "Error: No valid access token available. Please run `opencode auth login` to re-authenticate.";
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/plugin.ts` around lines 1351 - 1371, The changed block omits semicolons
on several statements (variable declarations and return lines) causing
inconsistency with the file style; add trailing semicolons to the statements
around projectContext/ensureProjectContext, the return in the catch, the
projectId assignment, the accessToken assignment, the if condition branch that
calls refreshAccessToken and its catch return, and the final return message so
lines referencing ProjectContextResult, ensureProjectContext, projectId,
accessToken, accessTokenExpired, and refreshAccessToken all end with semicolons
matching the rest of the file.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 539afff and bb3db28.

📒 Files selected for processing (1)
  • src/plugin.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🔇 Additional comments (1)
src/plugin.ts (1)

1351-1384: Core fix looks correct — ensureProjectContext properly replaces the parseRefreshParts + "unknown" fallback.

The project ID resolution now matches the model request path (compare lines 1784–1809), and the past review feedback about using projectContext.auth for both accessTokenExpired and refreshAccessToken has been addressed.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/plugin.ts`:
- Around line 1351-1371: The changed block omits semicolons on several
statements (variable declarations and return lines) causing inconsistency with
the file style; add trailing semicolons to the statements around
projectContext/ensureProjectContext, the return in the catch, the projectId
assignment, the accessToken assignment, the if condition branch that calls
refreshAccessToken and its catch return, and the final return message so lines
referencing ProjectContextResult, ensureProjectContext, projectId, accessToken,
accessTokenExpired, and refreshAccessToken all end with semicolons matching the
rest of the file.

ljepson pushed a commit to ljepson/opencode-antigravity-auth that referenced this pull request Feb 20, 2026
…ss review issues

- PR NoeFabris#476: guard isOAuthAuth against undefined/null (auth.ts)
- PR NoeFabris#465: use ensureProjectContext for google_search project‑ID resolution
- PR NoeFabris#460: throttle excessive file writes from account state updates
- Fix abort‑during‑cooldown error‑escape (wrap all  calls)
- Remove stale THINKING_RECOVERY_NEEDED sentinel branch
- Change abort status from HTTP 499 to standard 408 (Request Timeout)
- All tests pass, type‑check clean
ljepson pushed a commit to ljepson/opencode-antigravity-auth that referenced this pull request Feb 20, 2026
…ss review issues

- PR NoeFabris#476: guard isOAuthAuth against undefined/null (auth.ts)
- PR NoeFabris#465: use ensureProjectContext for google_search project‑ID resolution
- PR NoeFabris#460: throttle excessive file writes from account state updates
- Fix abort‑during‑cooldown error‑escape (wrap all  calls)
- Remove stale THINKING_RECOVERY_NEEDED sentinel branch
- Change abort status from HTTP 499 to standard 408 (Request Timeout)
- All tests pass, type‑check clean
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] google_search tool returns 404 — uses 'unknown' projectId instead of ensureProjectContext()

1 participant